// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <turbo/memory/arena.h>
#include <cantor/parser/ast/utils.h>
#include <cantor/parser/flags.h>
#include <nlohmann/json.hpp>
#include <cantor/proto/parser/ast_enum.pb.h>
#include <cantor/proto/parser/ast_node_type.pb.h>

namespace cantor::parser {

    struct Node;

    struct LocationInfo {
        int location{-1};
        int len{0};

        nlohmann::ordered_json to_json() const;
    };

    std::ostream &operator<<(std::ostream &os, const LocationInfo &loc);

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// Node - Base class for all AST nodes
    ///
    /// This is the root class for all AST (Abstract Syntax Tree) nodes. Each specific
    /// node type (e.g., statements, expressions, types) should inherit from this class.
    ///
    /// Key Responsibilities:
    /// - Provides common metadata like node type, location, and complexity flags
    /// - Supports polymorphic print and serialization (to_stream, to_json)
    /// - Allows propagation of print and plan cache flags
    ///
    /// This class is not intended to be used directly — always subclass for specific needs.
    ///////////////////////////////////////////////////////////////////////////////////////////////

    struct Node {
        /// Type of the node (used for runtime identification)
        const pb::ast::NodeType node_type = pb::ast::NODE_TYPE_NONE;

        /// Constructor to initialize the node type
        Node(pb::ast::NodeType t) : node_type(t) {
        }

        /// Virtual destructor
        virtual ~Node() {
        }

        /// join and sub query is complex
        bool is_complex = false;

        /// Source code location info (e.g., line/column)
        LocationInfo location;

        /// Sets the pointer to plan cache parameters
        virtual bool is_complex_node() ;

        /// Checks if this node or any of its children are complex
        virtual void print() const;

        /// Debug print function — outputs node type to stdout
        virtual void to_stream(std::ostream &os) const {
            KCHECK(false) << "not implemented ";
        }

        /// Converts the node to JSON representation
        virtual nlohmann::ordered_json to_json() const = 0;

        /// Helper: appends common node fields to a JSON object
        virtual nlohmann::ordered_json to_json_impl() const;

        /// Converts the node to a string via `to_stream`
        virtual std::string to_string() const;

        /// Collects placeholder references (e.g., for parameterized queries)
        virtual void find_placeholder(std::unordered_set<int> &placeholders) {
        }
    };

    std::ostream &operator<<(std::ostream &os, const Node *node);

    std::ostream &operator<<(std::ostream &os, const Node &node);
} // namespace cantor::parser
